﻿#if XBOX360

using System.Collections.Generic;

namespace Spacer {
	/// <summary>
	/// http://inlandstudios.com/en/?p=1093
	/// 
	/// HashSet for Xbox360.
	/// 
	/// NOTE:
	/// This HastSet was designed to minimize block allocations.  I could have 
	/// implemented it more like a true Hash; allocating an array of linked lists
	/// but this felt cleaner.  I don't know the internals of Dictionary<> but I'm 
	/// guessing it's similar to a heap or std::map<> in c++, which is generally 
	/// implemented as a binary search tree.
	/// </summary>
	/// <typeparam name="T"></typeparam>
	public class HashSet<T> : IEnumerable<T> where T : class {
		Dictionary<T,bool> data = new Dictionary<T,bool>();
		public int Count { get { return data.Count; } }

		// ----------

		public HashSet() {}

		public bool Add( T t ) {
			if( Contains(t) == false ) {
				data.Add( t, true );
				return true;
			}
			return false;
		}

		public bool Remove( T t ) {
			if( Contains(t) == true ) {
				data.Remove( t );
				return true;
			}
			return false;
		}

		public void Clear() {
			data.Clear();
		}

		public bool Contains( T t ) {
			return data.ContainsKey( t );
		}

		public IEnumerator<T> GetEnumerator() {
			return new ValueEnumerator( data );
		}

		System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
			return new ValueEnumerator( data );
		}

		public void CopyTo( T[] arr ) {
			data.Keys.CopyTo( arr, 0 );
		}

		// ----------

		struct ValueEnumerator : IEnumerator<T> {
			internal ValueEnumerator( Dictionary<T, bool> hashset ) {
				data = hashset;
				values = data.GetEnumerator();
			}

			Dictionary<T,bool> data;
			Dictionary<T,bool>.Enumerator values;

			public T Current { get { return values.Current.Key; } }
			public void Dispose() { values.Dispose(); }
			object System.Collections.IEnumerator.Current { get { return values.Current; } }
			public void Reset() { values = data.GetEnumerator(); }
			public bool MoveNext() { return values.MoveNext(); }
		}
	}
}

#endif